home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 2.1 / Amiga Developer CD v2.1.iso / Reference / Amiga_Mail_Vol2 / Archives / Plain / so91.lha / Scan / Find.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-10-23  |  12.0 KB  |  466 lines

  1. ;/* Find.c - Amiga Mail ExAll() example.
  2. lc -cfis -v -d0 -b0 -j73 Find.c
  3. blink from Find.o to Find lib lib:amiga.lib; if you don't have pragmas
  4. quit
  5.  *
  6.  * Pure code if pragmas are used.
  7.  * Tuesday, 16-Jul-91 16:21:14, Ewout
  8.  *
  9.  * Compiled with SAS/C 5.10a:
  10.  */
  11. /* (c)  Copyright 1991 Commodore-Amiga, Inc.   All rights reserved.
  12. The information contained herein is subject to change without notice,
  13. and is provided "as is" without warranty of any kind, either expressed
  14. or implied.  The entire risk as to the use of this information is
  15. assumed by the user.
  16. */
  17.  
  18. #include <exec/memory.h>
  19. #include <dos/dosextens.h>
  20. #include <dos/rdargs.h>
  21. #include <dos/exall.h>
  22.  
  23. #include <clib/exec_protos.h>
  24. #include <clib/dos_protos.h>
  25. #include <clib/utility_protos.h>
  26.  
  27. /* undef PRAGMAS if you don't have them */
  28. /* #define PRAGMAS */
  29. #undef PRAGMAS
  30. #ifdef PRAGMAS
  31. #include <pragmas/exec_pragmas.h>
  32. #include <pragmas/dos_pragmas.h>
  33. #include <pragmas/utility_pragmas.h>
  34. #else
  35. struct ExecBase *SysBase;
  36. struct DosLibrary *DOSBase;
  37. struct Library *UtilityBase;
  38.  
  39. #endif
  40.  
  41. /* ExAll buffersize to receive data in */
  42. #define BUFFERSIZE 512
  43. /* Default buffersize for hold fully qualified filenames */
  44. #define NAMEBUFFERSIZE 512
  45.  
  46. /* Used to pass data around to functions */
  47. struct FindControl
  48. {
  49.   struct DosLibrary *fc_DOSBase;
  50.   UBYTE          *fc_Parsebuffer;       /* Buffer which contains the parsed pattern */
  51.   ULONG           fc_Parselength;       /* The length of this buffer */
  52.   UBYTE          *fc_Namebuffer;        /* Buffer to hold the filename */
  53.   ULONG           fc_Namelength;        /* The length of that buffer */
  54.   BOOL            fc_Files;  /* BOOLEAN which tells if we should only look for files */
  55.   BOOL            fc_Dirs;   /* BOOLEAN which tells if we should only look for dirs */
  56.   BOOL            fc_All;    /* ALL keyword? */
  57. };
  58.  
  59. static UBYTE   *VersTag = "\0$VER: Find 37.1 (16.07.91)";
  60.  
  61. LONG            main(VOID);
  62. LONG            ScanDirectory(struct FindControl *, UBYTE *);
  63. BOOL            IsAssign(struct FindControl *, UBYTE *);
  64. LONG            MultiScanDirectory(struct FindControl *, UBYTE *);
  65. UWORD           StrLen(UBYTE *);
  66.  
  67. LONG
  68. main(VOID)
  69. {
  70. #ifdef PRAGMAS
  71.   struct DosLibrary *DOSBase;
  72.   struct Library *UtilityBase;
  73.  
  74. #endif
  75.   struct RDArgs  *readargs;
  76.   LONG            rargs[6];
  77.   struct FindControl *fc;
  78.   UBYTE          *pattern, **directories;
  79.   struct Process *process;
  80.   APTR            windowptr;
  81.   COUNT           i;
  82.   LONG            rc = 0, error = 0, fatalerror = 0;
  83.  
  84. #ifndef PRAGMAS
  85.   /* set up SysBase */
  86.   SysBase = (*((struct Library **) 4));
  87. #endif
  88.  
  89.   /* Fail silently if < 37 */
  90.   if (DOSBase = (struct DosLibrary *) OpenLibrary("dos.library", 37))
  91.   {
  92.     UtilityBase = DOSBase->dl_UtilityBase;
  93.  
  94.     rargs[0] = 0L;
  95.     rargs[1] = 0L;
  96.     rargs[2] = 0L;
  97.     rargs[3] = 0L;
  98.     rargs[4] = 0L;
  99.     rargs[5] = 0L;
  100.  
  101.     if (readargs =
  102.         ReadArgs("PATTERN/A,DIRECTORY/A/M,FILES/S,DIRS/S,ALL/S,BUFFER/K/N",
  103.                  rargs,
  104.                  NULL))
  105.     {
  106.  
  107.       if (fc = AllocMem(sizeof(struct FindControl), MEMF_CLEAR))
  108.       {
  109.  
  110. #ifdef PRAGMAS
  111.         fc->fc_DOSBase = DOSBase;
  112. #endif
  113.  
  114.         pattern = (UBYTE *) rargs[0];
  115.  
  116.         fc->fc_Parselength = StrLen(pattern) * 3;
  117.         if (fc->fc_Parsebuffer = AllocMem(fc->fc_Parselength, MEMF_CLEAR))
  118.         {
  119.  
  120.           /* Make pattern uppercase for possible character classes */
  121.           i = 0;
  122.           while (pattern[i])
  123.             pattern[i] = ToUpper(pattern[i++]);
  124.  
  125.           if ((ParsePatternNoCase(pattern,
  126.                                   fc->fc_Parsebuffer,
  127.                                   fc->fc_Parselength)) != -1)
  128.           {
  129.  
  130.             directories = (UBYTE **) rargs[1];
  131.  
  132.             fc->fc_Files = (BOOL) rargs[2];
  133.             fc->fc_Dirs = (BOOL) rargs[3];
  134.             fc->fc_All = (BOOL) rargs[4];
  135.  
  136.             /*
  137.              * Both set or cleared, clear both anyway. Easier checking later on.
  138.              */
  139.             if (fc->fc_Files == fc->fc_Dirs)
  140.               fc->fc_Files = fc->fc_Dirs = FALSE;
  141.  
  142.             if (rargs[5])
  143.               fc->fc_Namelength = *((LONG *) rargs[5]);
  144.  
  145.             if (fc->fc_Namelength < NAMEBUFFERSIZE || fc->fc_Namelength > 4096)
  146.               fc->fc_Namelength = NAMEBUFFERSIZE;
  147.  
  148.             if (fc->fc_Namebuffer = AllocMem(fc->fc_Namelength, MEMF_CLEAR))
  149.             {
  150.               process = (struct Process *) FindTask(NULL);
  151.               windowptr = process->pr_WindowPtr;
  152.               process->pr_WindowPtr = (APTR) - 1L;
  153.  
  154.               while (*directories)
  155.               {
  156.  
  157.                 /*
  158.                  * Check if this is a standalone assign which appears in the assign
  159.                  * list?
  160.                  */
  161.                 if (IsAssign(fc, *directories))
  162.                   error = MultiScanDirectory(fc, *directories++);
  163.                 else
  164.                   error = ScanDirectory(fc, *directories++);
  165.  
  166.                 if (error != 0)
  167.                   break;
  168.               }
  169.  
  170.               process->pr_WindowPtr = windowptr;
  171.  
  172.               FreeMem(fc->fc_Namebuffer, fc->fc_Namelength);
  173.             }
  174.             else
  175.               fatalerror = ERROR_NO_FREE_STORE;
  176.           }
  177.           else
  178.             fatalerror = ERROR_BAD_TEMPLATE;
  179.  
  180.           FreeMem(fc->fc_Parsebuffer, fc->fc_Parselength);
  181.         }
  182.         else
  183.           fatalerror = ERROR_NO_FREE_STORE;
  184.         FreeMem(fc, sizeof(struct FindControl));
  185.       }
  186.       else
  187.         fatalerror = ERROR_NO_FREE_STORE;
  188.  
  189.       FreeArgs(readargs);
  190.  
  191.     }
  192.     else
  193.       fatalerror = IoErr();
  194.  
  195.     /*
  196.      * Error handling: To be informative, errors are shown while scanning, so the
  197.      * file name which caused the error can be displayed. Other errors are shown
  198.      * here. Errors which occured in the main loop are considered fatal, others
  199.      * (except BREAK) just error.
  200.      */
  201.  
  202.     if (fatalerror)
  203.     {
  204.       error = fatalerror;
  205.       PrintFault(fatalerror, NULL);
  206.     }
  207.  
  208.     SetIoErr(error);
  209.     if (error != 0)
  210.     {
  211.       if (fatalerror)
  212.         rc = RETURN_FAIL;
  213.       else if (error == ERROR_BREAK)
  214.         rc = RETURN_WARN;
  215.       else
  216.         rc = RETURN_ERROR;
  217.     }
  218.  
  219.     CloseLibrary((struct Library *) DOSBase);
  220.   }
  221.   else
  222.     rc = RETURN_FAIL;
  223.   return (rc);
  224. }
  225.  
  226.  
  227. LONG
  228. ScanDirectory(struct FindControl * fc, UBYTE * source)
  229. {
  230. #ifdef PRAGMAS
  231.   struct DosLibrary *DOSBase = fc->fc_DOSBase;
  232.  
  233. #endif
  234.   LONG            vargs[1];
  235.   struct ExAllControl *excontrol;
  236.   struct ExAllData *ead, *buffer;
  237.   BPTR            sourcelock, namelock, olddirlock;
  238.   BOOL            exmore;
  239.   LONG            error;
  240.  
  241.   /*
  242.    * Because this function may be recursively, get a fresh buffer per function call.
  243.    */
  244.   if (buffer = AllocMem(BUFFERSIZE, MEMF_CLEAR))
  245.   {
  246.  
  247.     /* Get a lock on the start directory and make it the current directory */
  248.     if (sourcelock = Lock(source, SHARED_LOCK))
  249.     {
  250.       olddirlock = CurrentDir(sourcelock);
  251.  
  252.       if (excontrol = AllocDosObject(DOS_EXALLCONTROL, NULL))
  253.       {
  254.  
  255.         do
  256.         {
  257.           /* Get both file name and type to support FILES/DIRS kewords */
  258.           exmore = ExAll(sourcelock, buffer, BUFFERSIZE, ED_TYPE, excontrol);
  259.           error = IoErr();
  260.           if ((exmore == NULL && (error != ERROR_NO_MORE_ENTRIES)))
  261.           {
  262.             PrintFault(error, source);
  263.             break;
  264.           }
  265.           if (excontrol->eac_Entries == 0)
  266.             continue;
  267.  
  268.           ead = buffer;
  269.           do
  270.           {
  271.  
  272.             /* Check for CTRL-C */
  273.             if (SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)
  274.             {
  275.               error = ERROR_BREAK;
  276.               PrintFault(error, NULL);
  277.               exmore = FALSE;
  278.               break;
  279.             }
  280.  
  281.             /*
  282.              * Check if this one matches. If it does see if it is of the right type.
  283.              */
  284.             if (MatchPatternNoCase(fc->fc_Parsebuffer, ead->ed_Name))
  285.             {
  286.               if ((ead->ed_Type < 0 && fc->fc_Dirs == FALSE)
  287.                   || (ead->ed_Type > 0 && fc->fc_Files == FALSE))
  288.               {
  289.                 /* It is. Lock it and get the fully qualified file name */
  290.                 if (namelock = Lock(ead->ed_Name, SHARED_LOCK))
  291.                 {
  292.                   if ((NameFromLock(namelock,
  293.                                     fc->fc_Namebuffer,
  294.                                     fc->fc_Namelength)) == DOSTRUE)
  295.                   {
  296.                     vargs[0] = (LONG) fc->fc_Namebuffer;
  297.                     VFPrintf(Output(), "%s\n", vargs);
  298.                   }
  299.                   else
  300.                   {
  301.                     error = IoErr();
  302.                     PrintFault(error, ead->ed_Name);
  303.                   }
  304.                   UnLock(namelock);
  305.                 }
  306.                 else
  307.                 {
  308.                   error = IoErr();
  309.                   PrintFault(error, ead->ed_Name);
  310.                 }
  311.               }
  312.             }
  313.  
  314.             /*
  315.              * If the ALL keyword is used and this is a directory, step in it by
  316.              * calling this function recursively.
  317.              */
  318.             if (ead->ed_Type > 0 && fc->fc_All)
  319.             {
  320.               error = ScanDirectory(fc, ead->ed_Name);
  321.               if (error != 0)
  322.               {
  323.                 exmore = FALSE;
  324.                 break;
  325.               }
  326.             }
  327.             ead = ead->ed_Next;
  328.           } while (ead);
  329.         } while (exmore);
  330.  
  331.         FreeDosObject(DOS_EXALLCONTROL, excontrol);
  332.  
  333.       }
  334.       else
  335.         error = ERROR_NO_FREE_STORE;
  336.  
  337.       CurrentDir(olddirlock);
  338.       UnLock(sourcelock);
  339.     }
  340.     else
  341.     {
  342.       error = IoErr();
  343.       PrintFault(error, source);
  344.     }
  345.     FreeMem(buffer, BUFFERSIZE);
  346.   }
  347.   else
  348.     error = ERROR_NO_FREE_STORE;
  349.  
  350.   if (error == ERROR_NO_MORE_ENTRIES)
  351.     error = 0;
  352.   else if (error == ERROR_NO_FREE_STORE)
  353.     PrintFault(error, NULL);
  354.  
  355.   return (error);
  356. }
  357.  
  358. BOOL
  359. IsAssign(struct FindControl * fc, UBYTE * name)
  360. {
  361. #ifdef PRAGMAS
  362.   struct DosLibrary *DOSBase = fc->fc_DOSBase;
  363.   struct Library *UtilityBase = DOSBase->dl_UtilityBase;
  364.  
  365. #endif
  366.   struct DosList *doslist;
  367.   UBYTE          *assignname;
  368.   UCOUNT          assignlength;
  369.   LONG            position;
  370.   BOOL            result = FALSE;
  371.  
  372.   /* First lets check if this resembles a devicename. */
  373.   position = SplitName(name, ':', fc->fc_Namebuffer, 0, fc->fc_Namelength);
  374.  
  375.   if (position != -1)
  376.   {
  377.     /* Hmmm. */
  378.     if (name[position] == '\0')
  379.     {
  380.  
  381.       /*
  382.        * I guess it does. Lets see if we can find it in the assign list. Keep the
  383.        * DoSList locked as briefly as possible. This shouldn't take long.
  384.        */
  385.       if (doslist = AttemptLockDosList(LDF_ASSIGNS | LDF_READ))
  386.       {
  387.         while (doslist = NextDosEntry(doslist, LDF_ASSIGNS))
  388.         {
  389.  
  390.           /* It's a BPTR */
  391.           assignname = (UBYTE *) BADDR(doslist->dol_Name);
  392.           assignlength = assignname[0];
  393.  
  394.           if ((Strnicmp(assignname + 1, fc->fc_Namebuffer, assignlength)) == 0)
  395.           {
  396.             /* Yup, it is. */
  397.             result = TRUE;
  398.             break;
  399.           }
  400.         }
  401.         UnLockDosList(LDF_ASSIGNS | LDF_READ);
  402.       }    /* Can't lock DosList, don't bother */
  403.     }
  404.   }
  405.   return (result);
  406. }
  407.  
  408. LONG
  409. MultiScanDirectory(struct FindControl * fc, UBYTE * source)
  410. {
  411. #ifdef PRAGMAS
  412.   struct DosLibrary *DOSBase = fc->fc_DOSBase;
  413.  
  414. #endif
  415.   struct DevProc *cproc = NULL;
  416.   struct MsgPort *filesystemtask;
  417.   LONG            error;
  418.  
  419.   filesystemtask = GetFileSysTask();
  420.  
  421.   do
  422.   {
  423.     /* Find handler */
  424.     if (cproc = GetDeviceProc(source, cproc))
  425.     {
  426.       SetFileSysTask(cproc->dvp_Port);
  427.       if ((NameFromLock(cproc->dvp_Lock,
  428.            fc->fc_Namebuffer,
  429.            fc->fc_Namelength)) == DOSTRUE)
  430.       {
  431.         error = ScanDirectory(fc, fc->fc_Namebuffer);
  432.       }
  433.       else
  434.       {
  435.         error = IoErr();
  436.         PrintFault(error, source);
  437.       }
  438.  
  439.       if (error != 0)
  440.         break;
  441.     }
  442.     else
  443.     {
  444.       error = IoErr();
  445.       PrintFault(error, source);
  446.     }
  447.  
  448.     /* Handle multi-assign */
  449.   } while (cproc && (cproc->dvp_Flags & DVPF_ASSIGN));
  450.  
  451.   SetFileSysTask(filesystemtask);
  452.   if (cproc)
  453.     FreeDeviceProc(cproc);
  454.  
  455.   return (error);
  456. }
  457.  
  458. UWORD
  459. StrLen(UBYTE * string)
  460. {
  461.   UBYTE          *length = string + 1;
  462.  
  463.   while (*string++ != '\0');
  464.   return ((UWORD) (string - length));
  465. }
  466.